梦入琼楼寒有月,行过石树冻无烟

Spring cloud 概述

Spring cloud 是一个基于 Spring boot 的一个快速开发的微服务框架,有一句话是 小项目用 spring boot,大项目用 spring cloud,他主要九个非常重要且显著的特征。

REST

在介绍Spring cloud 各类特性和主要项目以及开源生态之前,我们需要了解表现层状态转换(REST,Representational State Transfer),由 Roy T. Fielding博士于 2000年在博士论文中提出。其提供出来的主要是一种互联网软件 设计风格,目的是方便软件或程序在互联网中互相传递信息。

在 Roy 的博士论文中我们可以看到其清楚的定义了下列六种知道原则,也就是我们将满足 REST 六种指导原则的风格称之为 RESTful:

  1. 客户端-服务器(Client-Server)
  2. 无状态(Stateless)
  3. 缓存 (Cache)
  4. 统一接口(Uniform Interface)
  5. 分层系统(Layered System)
  6. 按需编码(Code On Demand)

https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

在这之后根据这篇论文进行了详细和系统的完善,使得更加具有了可读性:https://restfulapi.net/

客户端-服务器(Client-Server)


在REST中,被第一个添加的则是客户端和服务器之间的架构风格约束,而他的关注点是客户端-服务器约束背后的原则。通过将用户界面与存数据存储问题进行分开, 这提高了用户界面跨平台的移植性以及简化了服务器组建,提高了扩展性。

无状态(Stateless)

根据客户端和-服务器通信中,我们假设通信本质是无状态(Stateless)的,即客户端到服务器的每个请求都不会存储上下文(会话完全保留在客户机上)。

而这些约束改善了 可见性、可靠性、可扩展性等,其中最为明显的则是可扩展性。

This constraint induces the properties of visibility, reliability, and scalability. Visibility is improved because a monitoring system does not have to look beyond a single request datum in order to determine the full nature of the request. Reliability is improved because it eases the task of recovering from partial failures. Scalability is improved because not having to store state between requests allows the server component to quickly free resources, and further simplifies implementation because the server doesn’t have to manage resource usage across requests.

他的缺点是可能会增加一系列请求中发送的重复数据,从而降低网络性能等方面。

缓存 (Cache)

缓存存在的意义则是在 REST 中提高网络效率,缓存主要被约束为请求的响应中内的数据隐式(或显示)标记为 可缓存或不可缓存

如果是可缓存的,则在客户端缓存有权为以后同样效果的请求重新应用该响应数据。

统一接口(Uniform Interface)

在 REST 架构风格中与其他类似架构风格有明显区分的就是组件之间的统一接口,他简化了整个系统架构并提高了交互的可见性。

为了实现和获得统一接口,需要多个架构约束来指导组件的行为,而 REST 则是由四个接口约束定义:

资源识别 (identification of resources)

请求中包含了各种独立资源的标识,如 Url等。除此之外还可以将自身的数据库信息以 HTML、XML、JSON等方式发送给客户端。

操纵资源 ( manipulation of resources through representations)

当客户端拥有资源标识后,就可以根据足够的信息删除这个资源

描述信息 (self-descriptive messages)

每个消息都包含了可以描述来如何处理这个信息的方式,如媒体类型(media type)以及最后修改时间 (modified time)

分层系统(Layered System)


分层系统的样式允许通过约束组件行为为使得每个组件 ”不能“ 看到与其直接交互的直接层之外的其他层,将架构由分层组成。2

需要注意的是很多文档都将 用超媒体驱动应用状态,“hypermedia as the engine of application state” 夹在里面,实际上他的意思为 ”超媒体 作为 应用程序状态引擎“

按需编码(Code On Demand)

按照 Roy 论文来理解,按需编码在 REST 其实是一个可选约束,并提供了一个非常不错的例子:

例如,如果已知组织内的所有客户端软件都支持 Java,则可以构建该组织内的服务,以便通过下载的Java 类来获得增强功能的好处。

但问题在于组织的防火墙可能会组织外部资源传输到 Java 小程序,对于 Web 的其他部分,某些客户端可能不支持该代码。

而按需编码所提供的 可选约束就允许我们设计一个在一般情况下支持所需行为的架构。

当然这是一种理解,而第二种理解就偏向与实际,大多数形式下返回的资源都以 XML或JSON表示,但是需要的时候,我们可以自由的返回可执行代码。

来支持自己应用程序的部分,根据按需编码的约束这是允许的,因为这属于 ”可选约束“。

应用与 Web 服务

我们可以根据 REST 的设计风格为 Web API 进行设计,符合其统一接口约束即可以被称之为 ”RESTful API“,他主要就是以统一接口的三个约束原则而定义的。

资源识别 我们可以理解为 资源地址的 URL,如 http://example.com/resources
传输的资源(描述信息) Web服务接受与返回的媒体类型,如 JSON、XML
而对 操纵资源则是所支持的一系列请求方法,如 POST、GET、PUT、DELETE 等。

如果你说你要实现一个 REST设计风格的 RESTful API,则可以参照下述例子:

1
2
3
4
5
6
7
8
1. 所有文章
GET http://www.example.com/list

2. 阅读某篇文章
GET http://www.example.com/list/{id}

3. 发布文章
POST http://www.example.com/list/release

推荐阅读 https://restfulapi.net/resource-naming/

特征

Spring cloud 很早就提供了下述特征的实现,但由于早期相关代码和介绍存在与 Spring cloud 的子项目 Spring Cloud Cluster 中,到最后被迁移至 Spring Integration 中。

这也是为什么 Spring cloud 在官方文档中说了自己的 xx 特征,但又很难找到相关文档的原因,这是因为人家早就把代码和文档迁移到了 Spring Integration 中了。

分布式\版本化管理(Distributed/versioned configuration)

Spring cloud Config 与 Spring cloud Bus 经常一起搭配使用,这可以让他无需重新启动服务可以刷新配置文件的信息。

通过 Spring Cloud Config 来统一管理服务配置,可以将所有服务的配置文件 放置在本地仓库或者远程仓库中。让Spring cloud config 配置中心来负责读取仓库的配置文件,而客户端(服务)从配置中心读取配置。

服务注册和发现(Service registration and discovery)

服务治理组件主要由 Eurake、Consul 等进行,他在此相当于交易的信息员,可以 发现 服务提供者(Service Provider),还可以将自己注册到 服务中心(Eureka Server)中

路由(Routing)

通过智能路由网管组件 Zuul、Spring Cloud Gateway 来实现智能路由和请求过滤功能。内部服务接口通过网关统一对外暴露,来避免内部服务敏感信息信息在未经授权情况下对外暴露。

服务到服务的通信(Service to service calls)

Service to service calls 在官方文档中并没有进行概述,所以本文仅是个人观点。

Spring cloud 中服务到服务的通信组要通过 Eureka 组件来调用微服务的顺序。

负载均衡(Load balancing)

负载均衡主要可以通过 Feign、Ribbon来实现负载均衡。

断路器(Circuit Breakers)

断路器使用服务容错组件 Hystrix、Resilience4j来控制服务的API接口荣段,以实现故障转移、服务限流、服务降级等功能。防止微服务系统发生 雪崩效应,可以使用 Hystrix Dashboard 组件监控 单个融断状态,使用 Hystrix Turbine 组件监控 多个服务的融断状态

全局锁(Global locks)

也许可以通过 https://github.com/spring-cloud-samples/locks#readme 来进行了解 Spring cloud 全局锁的作用。

全局锁(Global locks)是对某部分进行加锁,当你只需要将某个部分只处于 只读状态 时,可以使用,之后这些部分进行更新、删除等将会造成阻塞。

领导选举和集群状态(Leadership election and cluster state)

领导选举和集群状态(Leadership election and cluster state)由 Spring Cloud Cluster 所提供分布式系统集群功能,以及包含了领导选举、集群状态以及全局锁。

这些都被 Spring Integration 中的代码取代。

分布式消息传递(Distributed messaging)

通过消息总线(Bus)组件,数据流操作组件可以 Redis、RabbitMQ、Kafka等进行封装,来实现消息的接收和发送

主要项目


下述有些并不完全是 Spring cloud 自己的,而是通过根据 Spring boot 风格对这些组件进行封装,屏蔽了复杂的配置和原理,最终给开发人员提供了一个简单易懂和易部署以及平滑的的微服务框架。

Spring Cloud Config

Spring cloud config 是 spring cloud 的配置管理工具,通过此项目可以将配置信息放到远程服务器中,从而集中管理集群配置。除此之外还可支持:本地存储、git、subversion 三种方式,这些资源还可直接映射到 Spring 环境

Spring Cloud Netflix

各种 Netifix OSS组件,由 Eureka,Hystrix ,Zuul,Archaius 等集成。

Spring Coud Bus

服务实例与分布式消息传递 连接在一起的 事件总线,可以在集群中传播状态更改(如配置更改),还可与 Spring Cloud Config 联合实现热部署。

Spring Cloud Cloudfoundry

Spring cloud 集成了 Foundry ,他是由 VMware 第一个业界推出的开源 Paas(Platform as a Service,平台即服务)的云平台。支持多种框架、语言、运行环境、平台及应用服务,基于这些可让开发人员快速在几秒中能进行部署和扩展,提供了服务发现,还可以轻松的实现 SSO、OAuth2保护资源。

Spring Cloud Open Service Broker

为实现构建 Open Service Broker API(开放服务器代理接口),可以为开发人员能够为开发人员对平台(如Spring Foundry、Kubernetes)中运行的应用提供服务。

Spring Cloud Cluster

提供了分布式系统集群所需要的基础功能支持,如选举、集群状态一致性、全局锁、Tokens 等常见状态模式的抽象和实现。

Spring Cloud Consul

Consul 是由 HashiCorp 公司所使用 Go 所开发的服务治理项目

Spring cloud Consul 主要封装了 Consul 来实现服务治理、健康检查、key-Values 存储、数据中心集群的呢个。

Spring Cloud Security

提供对 Zuul 代理中复杂均衡的 OAuth2、REST 客户端和身份验证头中继的支持。

Spring Cloud Sleuth

Spring cloud sleuth 为 spring cloud 服务之间的调用提供了链路追踪,封装了 Dapper、Log-based 追踪(ELK)、Zipkin 和 HTrace 操作。

Spring Cloud Data Flow

针对现代运行时可组合的微服务应用程序的原生编排服务,易用于 DSL、拖放 GUI 和 restAPI 一起简化了基于微服务的数据管道整体编排。即提供了统一变成模型和托管服务,用于开发和执行 ETL、一种用于处理大规模数据的模式。

Spring Cloud Stream

一个轻量级事件驱动的微服务框架,用于快速构建可以链接到外部系统的应用程序。基于 Spring boot 创建,通过事件触发任务,封装了 Redis、Rabbit、Kafka等发送和接收消息,用来创建工业级的 Spring 应用。

Spring Cloud Stream Application

Spring cloud Stream 应用程序是现成的 Spring 引导应用程序,使用 spring cloud stream 中的 binder 抽象提供与外部中间件系统(ApacheKafka、RabbitMQ……)的集成。

Spring Cloud Task

一个短暂的微服务框架,主要用于进行微服务的任务管理和调度等。

Spring Cloud Task App Starters

Spring cloud 任务应用启动程序是 spring boot 应用程序,可以是任何进程,包括不会永远运行的 Spring 批处理作业,他们可以在有限的数据处理周期后 结束或停止

Spring Cloud Zookeeper

Spring cloud 集成了 Zookeeper,他是 Hadoop 和 Hbase 的重要组件,提供了配置维护、域名服务、分布式同步、组服务、服务治理等功能

Spring Cloud Connectors

使各种平台上的PaaS(Platform as a Service,平台即服务)应用程序能够轻松地连接到后端服务。也就是说可以通过他来链接到服务和从云平台获取操作的过程,拥有很强的扩展性,可用于构建云平台。

Spring Cloud Starters

一个 Spring boot 风格的启动应用项目,可以简化 Spring Cloud 使用者的依赖管理关系(在 Angel.SR2之后停止为一个项目,并与其他项目合并),为 Spring cloud 提供了一个 开箱即用 的依赖管理。

Spring Cloud CLI

Spring boot CLI 插件,用于在 Groovy 中快速创建 SPring Clound 组件应用程序,即通过 Spring cloud CLI 可以 快速构建云组件

Spring Clound Contract

Spring cloud 通过 CDC (Customer Driven Contracts,客户驱动合同)开发,基于JVM(Java 虚拟机,Java virtual machine)的应用提供了支持,为TDD(测试驱动开发)提供一种新的基于接口的测试方法。

Spring Cloud Gateway

Spring cloud Gateway 是一个基于Project Reactor 项目,为 Spring cloud 提供了一种简单和有效的方式来对 为服务的 API 进行路由

Spring Cloud OpenFeign

Spring cloud OpenFeign 由于封装声明试 Web Service 客户端的 Feign,可以让编写 Web Service client 变得容易。支持 Feign 注解和 JAX-RS 注解,支持热插拔的编码器和解码器,并支持 Feign 在 Spring MVC 中使用,由于整合了 Ribbon 和 Eureka 可以在使用 Feighn 时提供负载均衡。

Spring Cloud Pipelines

Spring Cloud Pipelines 提供了一个可靠的部署管道,其中包含了一些步骤,来确保应用程序可以零停机的方式部署,并且在出现问题时可以轻松的回滚。

Spring Cloud Function

Spring Cloud Function 提供了一通用的模型,在类似与 AWS Lambda 这种 FaaS(Function as a Service,函数驱动服务)平台上部署函数软件。

Netfix 项目

除了 Spring cloud 项目本身,其他厂商也对其微服务等开源产品作出巨大的公司,如 Netfix 和 Alibaba 等公司,但 Netfix 要早于 Alibaba 对微服务及其相关产品或项目的贡献。

Spring Cloud 集成了 Netfix 公司所开源的各种项目和组建其中主要以 Eureka、Hystrix、Zuul、Archaius 作为为代表项目。

Eureka

Eureka 是一个基于 REST 服务的服务治理组件,主要包含了服务注册和服务发现两个最为核心的功能。

Hystrix

Spring cloud 可以整合 Hystrix 来对微服务进行容错管理,即使将服务做成集群也不 100% 保证安全可用。为了防止服务与服务之间的依赖性,单个服务出现故障 从而导致整个为服务系统崩溃,则需要进行容错管理。

Zuul

Zuul 为 Spring cloud 提供了路由和过滤的功能,他是一种服务的统一入口,除此还提供了动态路由、监控、授权、安全、调度等功能。

Archaius

Spring cloud 整合了 Archaius 来进行 管理和配置 API,Archaius 提供了动态类型化属性、线程安全配置操作,轮询框架,回调机制等功能。

Archaius 可以实现出动态获取配置,如默认每隔60s从配置源读取一次内容,这样在修改配置文件后不需要重新启动服务,即可使得修改的内容生效

Alibaba 项目

在 2019年10月所发布的《颠覆性公司和商业模式》报告中,Alibaba 以 15% 成功位居第三位,百度、腾讯等均位列第十和第十一位。

Sentinel

Sentinel 是一个流控制组件,可以将流量作为切入点,从流量控制、熔断降级、系统负载保护等多个阶段保证服务的稳定性。

Nacos

Nacos 是一个服务治理的项目,与 Eureka、Consul 一样,提供了动态服务发现、配置管理和服务管理平台。

RocketMQ

RocketMQ 是基于分布式高可用集群提供的低延迟、高可靠的消息发布/订阅服务,类似与 RabbitMQ 的一种消息中间件。

Dubbo

Dubbo 是一个高性能、轻量级的开源 Java 服务框架,提供了面向接口代理的高性能RPC(Romote Procedure Call,远程过程调用),智能容错、负载均衡、服务自动注册和发现、运行期流量调整、可视化服务治理与运维等。

Seata

Seata是一款分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。

Alibaba Cloud ACM

Alibaba Cloud ACM 是一个应用配置中心,用于分布式架构环境中对 应用配置进行集中的管理和推送。

Alibaba Cloud SchedulerX

Cron 是一个基于时间的任务管理系统,可通过 cron 在固定时间、日期、间隔的情况下运行任务。

除此之外他的表达式特别的不具有可读性:

1
2
3
4
5
6
7
8
# 文件格式說明
# ┌──分鐘(0 - 59)
# │ ┌──小時(0 - 23)
# │ │ ┌──日(1 - 31)
# │ │ │ ┌─月(1 - 12)
# │ │ │ │ ┌─星期(0 - 6,表示从周日到周六)
# │ │ │ │ │
# * * * * * 被執行的命令

1-6 * * * * echo hello world 及每小时的 1~6分钟内,都会都会打印 Hello,world符号。

更多可参考 https://zh.wikipedia.org/wiki/Cron

基于 Cron 表达式的任务调度服务,可以提供秒级、精准、高可靠、高可用的定时任务调度功能,可以支持 cron、fixed_rate、second_delay 定时调度,能精确到秒级别。

架构对比

Spring cloud

Dubbo

Dubbo 比 Spring cloud 少了很多配套项目(因为不是 spring 全家桶内的),所以 Dubbo 专注与 RPC 领域,未来将会成为微服务生态体系中一个重要的 组件,而不是 微服务的全面解决方案

lstio


lstio 主要使用网格服务 Service Mesh 架构来实现,因此在 lstio 中,服务之间的通信主要通过 Envoy 代理来使用 HTTP/1.1、HTTP2、gRPC、TCP 来进行,Pilot、Mixer、Citadel 来组成的控制平台。

pilot

为 Envoy 提供服务发现、流量管理、智能路由、错误处理(含超时、重试、融断)的功能,因此用户可以通过 Pilot 的 API 管理网络相关的资源对象。Pilot 会根据用户的配置和服务的信息将网络流量管理信息分发到各个 Envoy 中。

Mixer

主要为整个 集群执行访问控制、跨服务网格使用策略(Policy)、管理(Rate Limit、Quota)bing souji cong Envoy 代理和其他服务自动探测到的数据,Mixer 包含了一个非常灵活的模型插件。可以与各种主机环境和后端基础架构进行交互,他是一个独立于平台的组件

Citadel

提供了服务之间的认证和证书管理,能够自动升级到 TLS 协议

Sidecar

在原有的客户端和服务器端之间添加了一个代理程序。

Envoy

提供了服务发现,负载均衡和路由表动态更新的 API这些分别解决了 lstio 和 Envoy 的问题,Proxy 作为 SideCar 会和控制中心动心,来获取需要的服务之间的信息,以及回报服务调用的 Metrics(指标) 数据

Sprng cloud 优缺点

微服务优点

模块化开发

以上图作为参考,我们可以首先得知微服务是以 分布式 作为必要技术。有多个微小服务所组成的一个应用,由于他将一个功能划分为一个很小的服务,可以将一个微服务交给不同的开发人员或团队进行开发。

也就是说不同的开发团队可以同时完成多个属于自己任务范围内的 “微服务”,进行项目开发,因此可以 易于开发和维护,而不是向单一应用一样一个项目几百个文件夹,都涉及不同的功能和服务。

代码量

与单个服务相比,微服务由于功能只针对一个功能所进行提供服务。因此代码量不会像正常的单一应用较多,所以项目的启动速度是比单一应用较快的。(但这也不算是优点,因为启动时还很麻烦,一个一个启动多个微服务)

易于更新迭代

如果只是小型的项目迭代的话,那么微服务由于是多个服务应用组成的一个庞大服务,所以我们可以根据目标 功能对应的微服务 模块直接进行修改后上传。不需要向单体应用一样直接暂停项目并进行修改后发布。

技术栈

由于微服务是以业务单一性为原则的开发模式,因此他的开发也不会是统一一种语言,他可以是多个,且不冲突。

解耦

解耦是在设计模式中较为常见的名词之一,各类书籍中经常出现但就是不给你解释。解耦通俗来说就是两个东西 原来互相影响,现在然他们 分别发展,但不是完全的分别发展,而是在原有的基础上降低两者互相的依赖关系。其核心思想是最小职责,每个地方做一件事情。

通常情况下 松耦合 也可以被称之为 解藕,瞬间让此变得高端大气上档次。因此除了松耦合外,

他还有一个反意为 紧耦合,指的是两个模块之间相互影响且关系紧密,存在着互相关系调用。

具有弹性

由于微服务非常可以简单的实现 服务集群,通过 服务治理组件来实现服务的治理,通常都是两三个集群一起工作。一台蹦了还有另一台,另一台蹦了又换下一台的局面,可以保证服务的正常运行。除此之外还具有水平扩展独立以及扩展性高等优点。

微服务缺点

分布式复杂性

对微服务来说分布式架构是一个非常必要的技术,但因为分布式依赖服务较多,一旦其中某个 依赖服务 以及系统的容错能力都会带来挑战。

分布式事务问题

所谓分布式事务问题可以分为 可靠事件模式(Reliable Event Mode)、补偿模式(Confirm Cancel)、TCC(Try Confirm Cancel) 三种,用于解决分布式的 事务一致性问题

首先我们需要知道为什么要有服务一致性,假设你在 Wechat 中将 100RMB 转账给 B,那么 B 的 Wechat 钱包就会多 100RMB。但如果这个过程中 Wechat 服务崩了,那你将会少 100RMB,而B的钱包数额不变。

可靠事件模式(Reliable Event Mode)

他也被称之为 可靠事件记录协议(RELP,Reliable Event Logging Protocol),是一种用于计算机网络中记录 计算机数据的网络协议

他可以提供消息的可靠传递,常用与不能让数据丢失的环境,如转账。在这里我们需要认清 可靠事件记录协议和可靠事件模式,在通常的情况下,可靠事件模式是可靠事件记录协议的实现

一般情况下事件操作可以被分为三种可能,分别为:

  1. 操作成功,投递事件
  2. 操作失败,投递事件失败
  3. 操作成功,投递失败,抛出异常 | 回滚
本地事件表

因此可靠事件模式主要通过 本地事件表和外部事件表 两者来就进行可靠事件投递。

本地事件表通过将事件和业务数据保存在同一个数据库中,来以一个额外的 事件恢复服务 来恢复事件。

原子性指一个操作不可中断,要么全部成功,要么全部失败的原则即称之为 原子性。

这些都将会由本地事务来保证更新业务的发布事件中的不可中断,要么全部成功,要么全部失败,即原子性。

外部事件表


外部事件表是针对本地事件表出现的问题,单个提出外部事件表的方法。将 事件持久话到外部事件系统服务中,事件系统需要提供一个实时的事件服务以用于接收 为服务发布的事件 。与此同时还需要提供一个恢复服务来确定和恢复事件。

事物提交前,业务系统会通过实时事件服务向系统请求发送事件,事件系统 只记录事件但并不发送

之后业务服务提交后,通过实时事件服务向 =>事件系统 确认发布,事件得到确认后 事件系统 进行发布到消息代理。

当业务系统回滚时,通过实时事件向时间系统去取消事件。假设事件系统的事件恢复服务定期找到未确定发送事件向业务服务查询状态时,根据业务服务返回的状态来决定事件是否需要发布。

补偿模式(Confirm Cancel)


补偿模式主要有 业务异常和技术异常 两个概念,是自身业务所造成的。而技术异常则是非业务逻辑产生的一系列问题,如网络异常等。


因此补偿模式需要使用一个 额外的协调服务来协调微服务保证一致性,这时候协调服务通过按照顺序调用服务,如果某个服务出现异常则直接取消之前所有已经成功调用的服务(所以他也具有原子性)。

也就是说当数据文件为空时提交,那么之前所填写的端口信息以及提交数据都将会被取消,而这所取消的就是一个 补偿

TCC 模式(Try Confirm Cancel)

TCC 模式由 Try、Confirm、Cancel 三个接口,一个完整的 TCC应用由 主业务、若干个业务服务 组成和发起,并最后通过主业务完成整个活动。

TCC 三个接口分别意思为:

  1. try:完成所有业务检查,预留必须存在的业务资源
  2. Confirm:执行业务,不做任何业务的检查和分析,只是用 try 阶段所预留的业务资源,Confirm 操作满足幂等性。

幂等性,就是说一个系统,在同样情况下一次请求和 重复 多次请求对资源造成一致的就是幂等性。

  1. Cancel 释放 try 阶段预留资源(满足幂等性?)

主业务服务调用所有的业务的 try 操作,之后在活动管理器中登记所有业务服务,当所有业务服务的 try 操作都调用成够后或从某个业务服务的 try 操作失败进入 confirm 阶段。

活动管理器根据 try 执行结果来执行 confirm or cencel 操作,如果 try 操作所有都成功则从活动管理器中调用所有 confirm 操作,否则将调用 cancel 来释放 try 预留资源。

分布式同步调用

分布式的同步调用及主要是在不确定环境中无法保证所依赖服务,但可以保证自己可以正常提供服务的情况。

SEDA

阶段式服务器模型(SEDA,Staged event-driven architencure)他是一个软件架构模型,可以将复杂的事件驱动的应用分解为一系列通过队列链接的阶段(Stage)。

在上述中 “分布式的同步调用及主要是在不确定环境中无法保证所依赖服务,但可以保证自己可以正常提供服务的情况。”就可以通过使用 SEDA 进行解决。

拥用一句话概括就是 将请求出来过程划分为多个阶段,不同资源消耗阶段,并使用不同数量的线程进行处理

接口调整

由于微服务数量可能会有很多,因此如果需要调整接口时则需要话费很大的时间。除了调整外还需要写其接口文档,来进行管理。

而接口文档可以从中心点引入很多下游问题,如接口文档的管理和更新等。

Spring cloud 微服务设计原则

AKF 可扩展性原则


Spring cloud 的单一设计原则可以让微服务更加优雅。在这个原则之下所开发的微服务项目通常 只关注单一的功能,有限的业务逻辑 最终完成一个有限的业务逻辑。

就比如 AKF 拆分原则即 扩展立方体(Scalability Cube)或 AKF Scale Cube,需要注意的是 AKF 并不是什么单词缩写,而是一个公司的名称。


我们可以直接概括下这三个轴的主要左右,其中Y轴是功能划分以及基于不同业务之间的划分。而 X轴则是水平扩展,北其名曰水平复制,来砸钱解决问题(加服务器)。最后就是Z轴,Z轴主要左右就是数据区分,来关注服务和数据的优先级进行划分。

Y Axis


Y 轴会会根据基于不同业务之间的整体应用拆分为多个服务,每个服务主要会实现一个单个功能。之后以 Eureka 服务治理为例,通过服务中心来进行治理,最终架构如上所示。

X Axis


X 轴主要是水平扩展,通过复制服务与数据来解决可用性及微服务集群的问题,也就是说将微服务运行多个实例(集群),来通过集群负载均衡的模式来提升服务整体的可用性。

Z Axis

Z轴主要就是区分数据,通常Z轴扩展有两种方案分别为 单元化架构以及数据分区 两种,以大数据时代的今天可能两者都会被使用,

单元化架构

单元化架构的选择主要根据服务的类型以及对象单元是否符合来进行区分,如客户端对服务端节点的选择都将是单元自成一体。

数据分区

数据区分也叫分区(Shard),他其实就是区分数据的,比如说我们可以根据年龄、注册时间来区分数据。通常会包含一下几个数据划分的方式,这也是最为常见的:

  1. 数据类型
  2. 数据范围
  3. 数据热度
  4. 数据分区

这四种最为常见的我们可以在很多大型应用中看到,如 bliblibli 弹幕网,因为咱们也没有看过他们的源代码,但是我们可以随便以肉眼可见的观察下,就会发现他们做了一个非常细致的数据区分。

服务自治

说到 Spring cloud,我们从第三节到现在就一直说他多么多么服务自治,看上去非常高端且难懂。实际上服务自治简单来讲就是 每个微服务都具有独立性质,及运行、开发、测试、构建、部署 且包含数据库都可独立运行的服务。而过多或依赖其他微服务,并与其高度解耦,除此之外我们将此称之为 服务自治。

服务自治也是名副其实的微服务设计原则,因为他可以打来很多的好处,如团队协作、技术栈、后续迭代、持续集成等多种优势。

轻量级通信

轻量级接口通信主要对其要求就是体量较轻,可以跨语言和跨平台之间的通信,以及可以不受技术限制,实现不同通信协议之间的通信,如:REST、RPC、AMQP、STOMP、MQTT等。

接口明确原则

而接口明确原则,则是为了确保之后微服务之间不断的完善,导致因为某个接口的变化而其他服务集群需要进行调整,为了避免此类令人烦恼的事情再次发生,则需要让这些接口在设计开发的时候更加的具有通用性。

容错性设计原则

容错性设计原则也被称之为弹性设计,即依赖服务宕机、网络或硬件出现问题时可以暂停使用服务,切换下一个资源,在后续我们将会以集群的方式解决这个问题。除此之外也有很多成熟可靠的方案进行选择,如 Hystrix 延迟和容错库。

自动化原则

自动化测试

自动化原则主要会分为自动化测试、自动化监控和自动化部署等三种非常主要的自动化方案。其中自动化测试可以减轻测试负担,可以保障微服务的模块在高流量的情况下可访问。

自动化监控

而自动化监控则是监控微服务状态,发现问题以及错误计数等来便于解决和发现问题,也可以根据监控状态来调整负载,来保证服务的稳定性和高可用等。在 Spring cloud 项目中,提供了一个为服务可用性监控 Spring Boot Admin 组件。

自动化部署

自动化部署指的是将代码自动部署到生产环境中,来减少项目发布的时间,目前可以通过 Jenkins + Fastlane 来搭配使用。

Spring cloud 业务拆分与管理模式

Domain Driver Design(DDD)


在微服务设计中,我们通常会存在一种不知道如何进行划分的问题,到底是根据功能、组织结构进行划分还是其他方式。

而为了解决这种问题,领域驱动设计(Domain Driver Design)提供了一种划分方法论,说白了就是可以解决微服务划分时遇到的问题。

首先,DDD 主要结构为四层,分别为 基础设施层 (Infrastructure)、领域层 (Domain)、应用层 (Application)、用户界面层 (Interfaces)(也被称为表示层、展现层、接口层)

领域

首先,我们需要通过 DDD 来指导我们的划分方法,而不是让他主导我们,从而让我们更加困惑。因此我们需要知道一件事情,就是 分清问题和方案,问题是需要解决的,而方案是用来解决问题的。

当谈论领域的时候(含子域、通用子域)实际上都是在讨论问题域,而问题域就是 我们需要解决什么问题

而到 限界上下文、聚合、实体、仓库 这些实际上是在 谈论解决方案 来解决领域时提出的问题。

在搜索领域中,我们可以从其主页面中来看出遇到的一些非常典型的问题:

  1. 如何保持知名度
  2. 如何让搜素变得更精准
  3. 如何找到一个合适的度进行营销

而这些问题的解决问题的方案可以是:

  1. 与浏览器之间进行绑定
  2. 加大数据爬取和关键词的定位
  3. 与搜索结果中布局一致

设计

在设计中,主要解决的就是让领域专家和技术专家深入合作,并建立一个软件问题提模型,而这个模型主要可以解决:

  1. 可以表达领域概念和业务流程
  2. 每个领域都有自己的解决方案

这就是设计在 DDD 主要的作用,DDD 是一种基于领域为中心来驱动的软件的开发思想,可以通过此来帮助我们解决复杂的业务问题,因此需要对每个 领域提出问题来对应一个领域模型,来解决问题

模型

在 DDD 中,主要将模型划分为四层,分别为基础层(Infrastructure)、领域层(Domain)、应用层(Application)、用户界面层(Interfaces),这些被简称为 IDAI。

通俗来讲模型就是一个解决方案空间,是一个为了准确定义需要问题而构造的一个抽象模型。而模型主要可以解决类似与业务领域问题,以及分析满足系统的功能性要求即 IDAI。

专家

通过领域提出的问题我们可以得知,这些问题的提出基本上不是开发人员非常擅长的,所以此时需要 领域专家 来提出问题,由 技术专家 解决问题,这也是 DDD 成功实施的主要条件。

事务管理模式

事物管理模式(ACID,Atomicity Consistency Isolation Durability)要比 DDD 更好理解,他在上一章就以一小部分的形式出现了,当时我们所介绍的是原子性(Atomicity)。

一个逻辑工作单元需要成为事物,需要满足 ACID属性,分别为:

  1. A:原子性(Atomicity),事物操作中,要么全做,要么都不做
  2. C:一致性(Consistency),事务执行完后,从同样状态,转向另一个同样的状态(可以理解为要么是全部执行中,要么是全部暂停中)
  3. I :隔离性(Isolation),事务执行时不被打扰
  4. D:持久性(Durability),事务提交后,对数据的改变就是永久性的。

2/3PC

2/3PC 算法模式(Two / Three Phase Commit,二/三阶段提交)主要是为了让分布式系统在事务处理时 可以实现 ACID属性 所设计的算法。

2PC

首先我们可以将他看成两个阶段,一个是 欲提交,而另一个则是 提交 阶段,其中:

欲提交阶段


欲提交阶段从名字就可以看出他并不是真正的提交阶段,而是处于向资源管理器询问是否可以提交,这其中主要分为三个阶段:

  1. 向所有资源管理器发送询问
  2. 资源管理器执行事物操作,如资源上锁等
  3. 返回信息给事物管理器(成功情况下)
执行事务提交阶段


执行事务提交阶段可以理解为欲提交阶段后的一个过程,他的主要有四个流程,分别为:

  1. 请求提交:事务管理器向资源管理器发出提交请求
  2. 事务提交:资源管理器收到请求后,开始事务提交操作,完成后释放事务资源
  3. 反馈结果:完成事务提交之后,向事务管理器发送 已提交(ACK) 消息
  4. 完成事务:事务管理器收到了所有资源管理器反馈的 ACK 后即完成提交。

假如其中某个资源管理器返回了未提交,或者说等待超时,那么将会中断事务,其流程如下:

  1. 发送事务请求:事务管理器向资源管理器发送回滚请求
  2. 事务回滚:资源管理器通过撤销信息来执行事务回滚,释放事务资源
  3. 反馈事务回滚结果:完成事务回滚后发送 ACK (协调者发布)消息
  4. 中断事务:当事务管理器收到了来自所有参与者反馈的 ACK 消息后中断服务。
缺点
堵塞


尽管 2PC 看似非常的优秀,但是如果认真品一下就会发现,这么多资源管理器,如果只有中某个资源管理器在执行事物提交阶段的时候,返回了 未提交,之后的所有提交是不是都需要进行等待而无法继续完成操作?

单点

单点即一旦事务管理器出现了问题,那么整个 2PC 的提交将无法运转。或者说一旦在提交的时候出现了问题,那么所有的资源管理器都会处于锁定状态,从而无法继续提供服务。

3PC

3PC 和 2PC 不同之处在于他有三个阶段,分别为 欲提交(PreCommit)、可以提交(CanCommit)、提交(doCommit)。在3PC 中三个阶段都有一个核心的理念,即 询问时不会锁定资源管理器,除非所有人 Ack 了才开始锁,因此他解决了 2PC 的堵塞问题。

而单点问题 3PC 则通过假设资源管理器无法即时接收到来自事务管理器的信息,他们会默认执行 doCommit ,而不会一直卡在那里不动,最终导致无法提供服务。

TTY Try-Confirm-Cancel


TTY 主要有三个接口,分别为 尝试(Try)、确认(Confirm)、取消(Cancel)。会比 2/3PC 更加好理解,因此他三个阶段功能如下:

  1. Try:检查所有业务的 一致性、并预留业务资源保证在事务执行时不会被其他事务打扰
  2. Confirm:使用 Try 阶段预留的业务资源来执行业务
  3. Cancel:取消执行业务,并释放 Try 阶段预留资源

消息中间件模式


通过引入消息中间件,可以进行异步处理、系统解耦、事务管理。从而解决多个系统之间同步通信所造成的阻塞,并将这些耦合在一起。消息中间件模式与 TCC 同样是最终一致性来管理事务,而 2/3PC 则是强一致。

在这个过程中,主要有三个要素,分别是将数据消息投递到中间件服务器中,通过消息确认机制保证成功投递。然后通过消费者可以正常使用消息,最后来保证第一个事务先执行。

目前世面上主流的消息中间件有 Redis、ActiveMQ、RabbitMQ、RocketMQ、Kafka等。

Saga 模式


Saga是根据 Hector 和 Kenneth 与 1987 年所发表的论文 《sagas》作为理论基础而出现的补偿协议。

Saga 模式其主要的就是 将长事务拆分为多个且可交错运行的子事务合集 而这些子事务都保持一定的一致性,都将由 saga 事务协调器来进行协调。

如果每一个子事务都正常结束,则整个事务完成。假设有某个子事务失败,那么则整个事务失败,并根据相反顺序来执行补偿步骤。

需要注意的是,Saga 由一系列的 T 事务组成,每个 T都对应一个补偿动作 C,用于撤销 T 所造成的结果。

恢复策略

向后恢复

向后恢复(backward recovery),补偿所有已完成事务。如果某一个子任务失败,则之前所有成功的子事物即 整个saga执行结果撤销

向前恢复

向前恢复(forward recovery),将失败的事务重试,假设所有失败的业务最终都会成功,在这种情况下就没有补偿事务什么事情了,常见与必须成功的场景。‘

Paxos 一致性算法


Paxos 算法由 Lamport 所提出的一种基于消息传递的分布式一致性算法,也被认为是类似算法中最为有效的,因此使其获得了 2013年图灵奖,他的主要作用就是 在分布式系统中就某个值,来达成一致

角色

首先在 Paxos 算法中最终要的就是角色,非常重要,主要有三个,分别为:

  1. 提议者(Proposer)
  2. 决策者(Acceptor )
  3. 学习者(Learner)

决策

首先,提议者(Proposer) 提出议案(Proposal),信息中包含了案件编号(Proposer id)以及提议的值(Value)

之后 决策者(Acceptor) 参与决策,回应 提议者(Proposer) 提案,如果收到的提案(Proposal)获得多数 提议者(Acceptor) 的接受,则该提案被批准

最后 学习者(Learner) 来学习从会议中获得到达成一致的提案(value)。

2F+1 我们可以理解为,假设要是决策者 5个 同意 5个拒绝,那么就不会构成会议的决策。在这种情况下,如果有2倍的 决策者 人数并加一,就可以保证信息的正确,使得会议正常进行。

Paxos 算法允许运行在宕机故障的异步系统内,也不要求可靠的消息传递,他使用了多数机制保证了 2F(faulty)+1 的容错,即 2F(faulty)+1 个节点最多允许 F 个节点出现问题。

Spring cloud 跨服务查询与微服务部署概述

跨服务之间查询

在微服务中,如果需要服务之间与服务之间进行数据的查询,可以被称之为 “跨服务”,而进行这个过程的有两种,分别为 API 和 CQRS模式两种。

API 组合器模式


API 组合器模式由两个或多个服务提供者组成,服务提供者拥有数据服务(即数据库),API 组合器通过查询每个服务提供者的 API 结果并组合,来实现从多个服务检索数据库的查询。

CQRS


命令查询职责分离(CQRS,Command Query Responsibility Segregation),是由 Eiffel 语言之父 Betrand Meyer 提出的概念,简单来讲就是将业务上分离了 读(query)和写(command)的行为,就比人的睡和醒是两种行为。

  1. 命令(Command),不返回任何结果(void),但会改变对象状态,指增加、删除、修改
  2. 查询(Query)用于返回结果(void),不会改变对象状态

因此 CQRS 中主要强调 读(Query)和写(Command)的分离 ,可能当查询数据会有一些问题,如时间过时的数据问题,可以通过使用事件(Event)机制来解决问题并修改查询数据源。

微服务部署

部署模式


微服务的部署主要可以分为四种,这四周部署模式中主要通过下述方式进行:

  1. WAR、JAR 包运行
  2. 服务部署虚拟机运行
  3. 通过 Docker 或 Kubernetes 等容器化技术进行微服务部署
  4. Serverless 无服务器部署

无服务器(Serverless)通过应用 使用第三方功能或服务,不需要管理服务器,但不代表他不需要服务器,主要包括了:

功能即服务(Function as a Service,FaaS) 简单来讲就是功能运行在独立容器中,基于事件驱动,由第三方托管功能。

后端即服务(Backend as a Service,Baas) 使用第三方服务来达到目的。

升级(维护)模式

蓝绿部署


蓝绿部署(Blue-green deployment),可以称之为 可不停机维护,主要分为蓝(Blue)和绿(Green)两个版本,其流程如下:

  1. 当更新时,将所有访问流量分给绿色部分来提供服务,从而升级蓝色集群。
  2. 当蓝色集群升级完后,来将绿色流量切换到蓝色集群,从而升级绿色集群
  3. 升级完成后将访问流量分配到全部集群中

滚动部署


滚动部署(Rolling deployment),指每次只一个或多个服务暂停。进行更新,后将此服务继续投入使用,直到集群中所有服务都被更新或完成为止。

金丝雀发布(灰度发布)

为什么叫金丝雀发布?
在以前矿工开矿的时候,需要在下矿洞前需要检查下方是否有毒气,矿工会放一只金丝雀进去,来去探路是否有毒气。

金丝雀发布也叫灰度发布(Canary release / Grayscale release),其主要是一部分更新,一部分使用老版本,当新版本用户没什么建议的话,则全部将迁移到新版本中。

Spring cloud 云原生概述

目前我们所谈论的云原生大多数分为两个,一个由 spring 开发公司 Pivotal 所定义的,另一个则是由谷歌所牵头成立的 云原生计算基金会 (CNCF,Cloud Native Computing Foundation)。

本文我们仅理解 Pivotal 公司和部分 CNCF 所定义的为服务,其主要概述主要分为四类,分别为:

  1. 微服务
  2. DevOps
    3. CI\CD(持续集成和持续交付
  3. 容器化

微服务

读者可通过下一篇文章深度和实践中了解到微服务到底可以做什么,他的作用都会被理解,主要明确服务之间的解藕,多个服务集群。

DevOps

DevOps(Development Opertainos)组合,即开发和运维组合,可以减少应用程序发布的风险。

CI\CD(Continuous integration \ Continuous deployment),及持续集成和持续交付的所略词,其主要概念是通过应用程序的共建、测试和部署中实施自动化,在开发和运营团队架起桥梁,也是构成 DevOps 关键之一。

容器化

容器化即以容器为基础,在容器中运行的进程和应用,其 Docker 是应用最为广泛的容器引擎。通过容器封装让进程和应用成为一个独立的单元,并实现除了高水平的资源隔离,简化了维护。

除此之外还有 kubernetes 容器编排系统,主要用于容器管理和容器之间的负载均衡,都是实现容器话的关键。

安装

本文使用 1.8.0_202 和 Maven 3.6.0 进行演示和构建,读者可自行进行安装其环境。此时我们需要使用 Spring Assistant,有两种方式可以进行安装,分别是从 jetbrains 内的 插件社区中 https://plugins.jetbrains.com/plugin/10229-spring-assistant 进行获取,也可从 Plugins 内直接进行安装,搜索 Spring Assistant 之后重启 IDEA 即可。

⬅️ Go back